use crate::dao::*;
use rbatis::{DriverType, Error, Uuid};
use rbatis::wrapper::Wrapper;
use cores::db::DAOBase;
use cores::utils::get_rang_str;
use cores::{AppError, Result};


pub async fn registry_service(username: String, password: String) -> Result<User> {
    let user = User {
        id: Some(Uuid::new()),
        username: Some(username),
        password: Some(password),
        mobile_phone: None,
        email: None,
        is_active: true,
        delete_flag: false,
    };
    user.save().await
}

pub async fn fetch_user_by_id(id: String) -> Result<User> {
    match User::get(id).await {
        None => Err(AppError::notfound()),
        Some(user) => Ok(user)
    }
}

pub async fn fetch_user_by_username(username: String) -> Result<User> {
    let query = Wrapper::new(&DriverType::Mysql).eq("username", username);
    let users: Vec<User> = User::filter(query).await;
    match users.first() {
        None => Err(AppError::from_str("用户不存在", 402)),
        Some(user) => Ok((*user).clone())
    }
}

pub async fn registry_application_service(client_name: String, client_icon: String, redirect_url: String, user: User) -> Result<AuthClient> {
    let auth_client = AuthClient {
        id: Some(Uuid::new()),
        client_name: Some(client_name),
        client_icon: Some(client_icon),
        secret_key: None,
        redirect_url: Some(redirect_url),
        is_active: false,
        delete_flag: false,
        apply_user_id: user.id.unwrap(),
    };
    auth_client.save().await
}

pub async fn get_applications_by_user(user: User) -> Vec<AuthClient> {
    let application_list: Vec<AuthClient> = AuthClient::filter(
        Wrapper::new(&DriverType::Mysql)
            .eq("apply_user_id", user.id.unwrap())
    ).await;
    application_list
}

pub async fn gen_application_secret_key_service(id: String, user: User) -> Result<AuthClient> {
    let application: Option<AuthClient> = AuthClient::get(
        id
    ).await;
    if application.is_none() {
        return Err(AppError::notfound_msg("应用不存在"));
    }
    let mut application = application.unwrap();
    if application.apply_user_id != user.id.unwrap() {
        return Err(AppError::from_str("您不是应用所有者，无法生成密钥！", 402));
    }
    application.secret_key = Some(get_rang_str(32).unwrap());
    application.update().await
}

pub async fn fetch_application_by_id(id: String) -> Result<AuthClient> {
    match AuthClient::get(id).await {
        None => Err(AppError::notfound()),
        Some(app) => Ok(app)
    }
}

pub async fn grant_application(user: User, application: AuthClient) -> Result<()> {
    let query = Wrapper::new(&DriverType::Mysql).eq("user_id", user.id.unwrap()).eq("client_id", application.id.unwrap());
    match AuthUserClient::filter(query).await.first() {
        None => {
            let auth_user_client = AuthUserClient {
                id: Some(Uuid::new()),
                client_id: Some(application.id.unwrap()),
                user_id: Some(user.id.unwrap()),
                oauth_user_name: Some(user.username.unwrap()),
                delete_flag: false,
            };
            auth_user_client.save().await?;
            Ok(())
        }
        Some(_) => Ok(())
    }
}

pub async fn get_auth_applications_by_user(user: User) -> Vec<AuthClient> {
    let auth_apps: Vec<AuthUserClient> = AuthUserClient::filter(
        Wrapper::new(&DriverType::Mysql)
            .eq("user_id", user.id.unwrap())
    ).await;
    let app_ids: Vec<Uuid> = auth_apps.into_iter().map(move |a| a.client_id.unwrap()).collect();
    let application_list: Vec<AuthClient> = AuthClient::filter(
        Wrapper::new(&DriverType::Mysql)
            .r#in("id", &app_ids)
    ).await;
    application_list
}